package com.sptan.framework.exception;

import com.sptan.framework.core.ResultEntity;
import jakarta.validation.UnexpectedTypeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * GlobalExceptionHandler.
 *
 * @author lp
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 定义参数异常处理器.
     *
     * @param e 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public ResponseEntity<ResultEntity<String>> validateErrorHandler(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        return new ResponseEntity<>(toErrorResultEntity(bindingResult), HttpStatus.BAD_REQUEST);
    }

    /**
     * 定义参数异常处理器.
     *
     * @param e 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseEntity<ResultEntity<String>> validateErrorHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String message = "";
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            message = fieldError.getDefaultMessage();
        }
        log.error("[服务] - [捕获参数校验异常]", message);
        return ResponseEntity.ok(ResultEntity.error(message));
    }

    /**
     * 定义参数异常处理器.
     *
     * @param e 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(UnexpectedTypeException.class)
    @ResponseBody
    public ResponseEntity<ResultEntity<String>> validateErrorHandler(UnexpectedTypeException e) {
        log.error("[服务] - [捕获参数校验异常]", e.getMessage());
        return ResponseEntity.ok(ResultEntity.error(e.getMessage()));
    }

    /**
     * 定义异常处理器.
     *
     * @param exception 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ResultEntity<String>> sassExceptionHandler(BadRequestException exception) {
        log.warn("[服务] - [捕获业务异常]", exception);
        return ResponseEntity.ok(ResultEntity.error(exception.getMessage()));
    }

    /**
     * 定义异常处理器.
     *
     * @param exception 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler({AuthRequestException.class})
    public ResponseEntity<ResultEntity<String>> authExceptionHandler(AuthRequestException exception) {
        log.warn("[服务] - [捕获Auth异常]", exception);
        return ResponseEntity.ok(ResultEntity.error(HttpStatus.UNAUTHORIZED.value(),exception.getMessage()));
    }

    /**
     * 定义异常处理器.
     *
     * @param exception 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(DataAccessException.class)
    public ResponseEntity<ResultEntity<String>> dataAccessException(DataAccessException exception) {
        log.error("[服务] - [捕获SQL异常]", exception);
        return ResponseEntity.ok(ResultEntity.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage()));
    }

    /**
     * 定义异常处理器.
     *
     * @param exception 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(SQLException.class)
    public ResponseEntity<ResultEntity<String>> sqlException(SQLException exception) {
        log.error("[服务] - [捕获SQL异常]", exception);
        return ResponseEntity.ok(ResultEntity.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage()));
    }

    /**
     * 定义异常处理器.
     *
     * @param exception 当前平台异常参数对象.
     * @return org.springframework.http.ResponseEntity response entity
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResultEntity<String>> exception(Exception exception) {
        log.error("[服务] - [未捕获异常]", exception);
        return  ResponseEntity.ok(ResultEntity.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage()));
    }

    private ResultEntity<String> toErrorResultEntity(BindingResult bindingResult) {
        String errorMessage = "";
        List<String> errorMsg;
        if (bindingResult.hasErrors()) {
            List<FieldError> errorList = bindingResult.getFieldErrors();
            errorMsg = errorList.stream().map(err -> {
                return "字段:" + err.getField() + "不合法，原因:" + err.getDefaultMessage();
            }).collect(Collectors.toList());
            errorMessage = errorMsg.get(0);
        }
        return ResultEntity.error(errorMessage);
    }

}
